package com.example.makerspace.utils;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.example.makerspace.config.FileConfig;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.UUID;

@Component
public class FileUtils {
    public static String staticPath;

    public  static  String filePath;
    public static String staticUrl;
    public static String staticFile;
    public static String httpPrefix;
  private  final  static  String   testHttpPrefix="https://119.45.199.13:3035/static/";
   private  final  static  String  devHttpPrefix="https://nism.ytcata.com:443/static/";





    @Resource
    private FileConfig fileConfig;


    @PostConstruct
    public void init(){
        staticPath = fileConfig.getStaticPath();
        staticUrl = fileConfig.getStaticUrl();
        staticFile = fileConfig.getStaticFile();
        httpPrefix = fileConfig.getHttpPrefix();
        filePath=fileConfig.getFilePath();
    }

    /**
     * @param file
     * @return 文件的存储的绝对路径
     */
    public static String saveMultipartFile(MultipartFile file, String targetDirPath) {

        File toFile = null;
        if (file.equals("") || file.getSize() <= 0) {
            return null;
        } else {

            /*获取文件原名称*/
            String originalFilename = file.getOriginalFilename();
            /*获取文件格式*/
            String fileFormat = originalFilename.substring(originalFilename.lastIndexOf("."));

            String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
            toFile = new File(targetDirPath + File.separator + originalFilename);

            String absolutePath = null;
            try {
                absolutePath = toFile.getCanonicalPath();

                /*判断路径中的文件夹是否存在，如果不存在，先创建文件夹*/
                String dirPath = absolutePath.substring(0, absolutePath.lastIndexOf(File.separator));
                File dir = new File(dirPath);
                if (!dir.exists()) {
                    dir.mkdirs();
                }

                InputStream ins = file.getInputStream();

                inputStreamToFile(ins, toFile);
                ins.close();

            } catch (IOException e) {
                e.printStackTrace();
            }
            return absolutePath;
        }

    }
    public static String saveMultipartFile2(MultipartFile file, String targetDirPath, String DirPath) {

        File toFile = null;
        if (file.equals("") || file.getSize() <= 0) {
            return null;
        } else {

            /*获取文件原名称*/
            String originalFilename = file.getOriginalFilename();
            /*获取文件格式*/
            String fileFormat = originalFilename.substring(originalFilename.lastIndexOf("."));

            String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
            toFile = new File(DirPath + File.separator + originalFilename);

            String absolutePath = null;
            try {
                absolutePath = toFile.getCanonicalPath();

                /*判断路径中的文件夹是否存在，如果不存在，先创建文件夹*/
                String dirPath = absolutePath.substring(0, absolutePath.lastIndexOf(File.separator));
                File dir = new File(dirPath);
                if (!dir.exists()) {
                    dir.mkdirs();
                }

                InputStream ins = file.getInputStream();

                inputStreamToFile(ins, toFile);
                ins.close();

            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println("targetDirPath"+targetDirPath);
            System.out.println("originalFilename"+originalFilename);
            return targetDirPath+"/"+originalFilename;
        }

    }

    //获取流文件
    private static void inputStreamToFile(InputStream ins, File file) {
        try {
            OutputStream os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            ins.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除本地临时文件
     *
     * @param file
     */
    public static void deleteTempFile(File file) {
        if (file != null) {
            File del = new File(file.toURI());
            del.delete();
        }
    }

    // 文件加载
    public static MultipartFile getMultipartFile(String path){
        InputStream inputStream = null;
        try{
            inputStream = new FileInputStream(path);
        }catch (FileNotFoundException e){
            e.printStackTrace();
            throw new RuntimeException("文件不存在");
        }
        FileItem fileItem = createFileItem(inputStream, path.substring(path.lastIndexOf("\\") + 1));
        return new CommonsMultipartFile(fileItem);
    }

    public static FileItem createFileItem(InputStream inputStream, String fileName) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        FileItem fileItem = factory.createItem("file", MediaType.MULTIPART_FORM_DATA_VALUE, true, fileName);
        int read = 0;
        OutputStream os = null;
        byte[] buffer = new byte[10 * 1024 * 1024];
        try {
            os = fileItem.getOutputStream();
            while ((read = inputStream.read(buffer, 0, 4096)) != -1) {
                os.write(buffer, 0, read);
            }
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
            throw new IllegalArgumentException("文件流输出失败");
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return fileItem;
    }


//    文件下载
    public static void downloadFile(HttpServletResponse response, String filePath){
        // 通过response输出流将文件传递到浏览器
        // 1、获取文件路径
        // 2.构建一个文件通过Paths工具类获取一个Path对象
        Path path = Paths.get(filePath);
        // 判断文件是否存在
        if (Files.exists(path)) {
            // 存在则下载
            // 通过response设定他的响应类型
            // 4.获取文件的后缀名
            String fileSuffix = filePath.substring(filePath.lastIndexOf("/") + 1);
            // 5.设置contentType ,只有指定contentType才能下载
            response.setContentType("application/octet-stream");
            // 6.添加http头信息
            // 因为fileName的编码格式是UTF-8 但是http头信息只识别 ISO8859-1 的编码格式
            // 因此要对fileName重新编码
            try {
                response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileSuffix, "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            // 7.使用Path 和response输出流将文件输出到浏览器
            try {
                Files.copy(path, response.getOutputStream());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //    文件下载
    public static void downloadFile2(HttpServletResponse response){
        // 通过response输出流将文件传递到浏览器
        // 1、获取文件路径
        // 2.构建一个文件通过Paths工具类获取一个Path对象
        Path path = Paths.get(filePath);
        // 判断文件是否存在
        if (Files.exists(path)) {
            // 存在则下载
            // 通过response设定他的响应类型
            // 4.获取文件的后缀名
            String fileSuffix = filePath.substring(filePath.lastIndexOf("/") + 1);
            // 5.设置contentType ,只有指定contentType才能下载
            response.setContentType("application/octet-stream");
            // 6.添加http头信息
            // 因为fileName的编码格式是UTF-8 但是http头信息只识别 ISO8859-1 的编码格式
            // 因此要对fileName重新编码
            try {
                response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileSuffix, "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            // 7.使用Path 和response输出流将文件输出到浏览器
            try {
                Files.copy(path, response.getOutputStream());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static void downloadFile3(HttpServletResponse response,String filePath){
        // 通过response输出流将文件传递到浏览器
        // 1、获取文件路径
        // 2.构建一个文件通过Paths工具类获取一个Path对象
        Path path = Paths.get(filePath);
        // 判断文件是否存在
        if (Files.exists(path)) {
            // 存在则下载
            // 通过response设定他的响应类型
            // 4.获取文件的后缀名
            String fileSuffix = filePath.substring(filePath.lastIndexOf("/") + 1);
            // 5.设置contentType ,只有指定contentType才能下载
            response.setContentType("application/octet-stream");
            // 6.添加http头信息
            // 因为fileName的编码格式是UTF-8 但是http头信息只识别 ISO8859-1 的编码格式
            // 因此要对fileName重新编码
            try {
                response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileSuffix, "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            // 7.使用Path 和response输出流将文件输出到浏览器
            try {
                Files.copy(path, response.getOutputStream());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }



    public static void deleteFile(String path) {
        if(StringUtils.isBlank(path)){
            return;
        }
        File file = new File(path);
        file.delete();
    }
    public static void deleteFile2(List<String> path) {
        if(path.size()==0){
            return;
        }
        for(int i=0;i<path.size();i++){
            File file = new File(path.get(i));
            file.delete();
        }
    }


    /**
     * 删除单个文件
     * @param   sPath    被删除文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public boolean deleteFile3(String sPath) {
        Boolean flag = false;
        File file = new File(sPath);
        // 路径为文件且不为空则进行删除
        if (file.isFile() && file.exists()) {
            file.delete();
            flag = true;
        }
        return flag;
    }
    /**
     * 删除目录（文件夹）以及目录下的文件
     * @param   sPath 被删除目录的文件路径
     * @return  目录删除成功返回true，否则返回false
     */
    public boolean deleteDirectory(String sPath) {
        //如果sPath不以文件分隔符结尾，自动添加文件分隔符
        if (!sPath.endsWith(File.separator)) {
            sPath = sPath + File.separator;
        }
        File dirFile = new File(sPath);
        //如果dir对应的文件不存在，或者不是一个目录，则退出
        if (!dirFile.exists() || !dirFile.isDirectory()) {
            return false;
        }
        Boolean flag = true;
        //删除文件夹下的所有文件(包括子目录)
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            //删除子文件
            if (files[i].isFile()) {
                flag = deleteFile3(files[i].getAbsolutePath());
                if (!flag) break;
            } //删除子目录
            else {
                flag = deleteDirectory(files[i].getAbsolutePath());
                if (!flag) break;
            }
        }
        if (!flag) return false;
        //删除当前目录
        if (dirFile.delete()) {
            return true;
        } else {
            return false;
        }
    }

    public static String getBriefPath(String path) {
        if(StringUtils.isBlank(path)){
            return path;
        }
        return path.substring(path.indexOf(staticPath) + staticPath.length());
    }
    public static String getRealUrl(String path) {
        return devHttpPrefix+ FileUtils.getBriefPath(path);
    }
}
